/*
 * GNU LESSER GENERAL PUBLIC LICENSE
 * Version 3, 29 June 2007
 *
 * Copyright (C) 2023 Huawei Device Co., Ltd.
 *
 * The Free Software Foundation may publish revised and/or new versions of the GNU Lesser
 * General Public License from time to time. Such new versions will be similar in spirit to the
 * present version, but may differ in detail to address new problems or concerns.

 * Each version is given a distinguishing version number. If the Library as you received it
 * specifies that a certain numbered version of the GNU Lesser General Public License “or any
 * later version” applies to it, you have the option of following the terms and conditions either
 * of that published version or of any later version published by the Free Software Foundation. If
 * the Library as you received it does not specify a version number of the GNU Lesser General
 * Public License, you may choose any version of the GNU Lesser General Public License ever
 * published by the Free Software Foundation.

 * If the Library as you received it specifies that a proxy can decide whether future versions of
 * the GNU Lesser General Public License shall apply, that proxy's public statement of
 * acceptance of any version is permanent authorization for you to choose that version
 * for the Library.
 */
import Zlib from "@ohos.zlib";
import fs from '@ohos.file.fs';
import Resources from "../domain/Resources";
import MediaType from "../domain/MediaType";
import ResourceUtil from "../util/ResourceUtil";
import EpubResource from "../domain/EpubResource";
import MediaTypeService from "../service/MediaTypeService";

export default class ResourcesLoader {
    public static loadResources(inZipPath: string, defaultHtmlEncoding: string, lazyLoadedTypes?: Array<MediaType>): Resources {
        return this.readerOutZipFiles(inZipPath, defaultHtmlEncoding, lazyLoadedTypes);
    }

    public static loadResourcesZip(inZipPath: string): Promise<string> | null {
        if (inZipPath == "" || !inZipPath.toLowerCase().endsWith(".epub") || !fs.accessSync(inZipPath))
            return null;
        return new Promise(result => {
            let newPath = inZipPath.replace(".epub", ".zip")
            fs.rename(inZipPath, newPath).then(() => {
                console.info("rename succeed");
                let outFile = inZipPath.substring(0, newPath.length - ".zip".length);
                if (fs.accessSync(outFile))
                    fs.rmdirSync(outFile);
                fs.mkdir(outFile).then(() => {
                    var options = {
                        level: Zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION,
                        memLevel: Zlib.MemLevel.MEM_LEVEL_DEFAULT,
                        strategy: Zlib.CompressStrategy.COMPRESS_STRATEGY_DEFAULT_STRATEGY
                    };
                    Zlib.decompressFile(newPath, outFile, options).then((data) => {
                        console.log("unzipFile result" + data);
                        result(outFile)
                    }).catch((err) => {
                        console.log("catch((err)=>" + err);
                    }).finally(() => {
                        fs.renameSync(newPath, inZipPath);
                    })
                })
            }).catch(function (err) {
                console.info("rename failed with error:" + err);
            })
        })
    }

    public static readerOutZipFiles(outZipPath: string, defaultHtmlEncoding: string, lazyLoadedTypes?: Array<MediaType>): Resources {
        let result = new Resources()
        return ResourcesLoader.readerDir(outZipPath, defaultHtmlEncoding, lazyLoadedTypes, result);
    }

    private static readerDir(outZipPath: string, defaultHtmlEncoding: string, lazyLoadedTypes?: Array<MediaType>, result?: Resources): Resources {
        console.info("-----ResourcesLoader.ets--------------init---readerDir-----------------")
        try {
            let dirs = fs.listFileSync(outZipPath);
            for (let dir of dirs) {
                if (dir) {
                    let stat = fs.statSync(`${outZipPath}/${dir}`);
                    if (stat.isFile()) {
                        result.add(ResourcesLoader.readerFile(outZipPath, defaultHtmlEncoding, dir));
                    } else if (stat.isDirectory()) {
                        result = this.readerDir(outZipPath + "/" + dir, defaultHtmlEncoding + "/", lazyLoadedTypes, result);
                    }
                }
            }
        } catch (e) {
            console.error(e);
        }
        console.info("-----ResourcesLoader.ets---readerDir()--------------result----" + result);
        return result;
    }

    private static readerFile(dirPath: string, defaultHtmlEncoding: string, dirName: string): EpubResource {
        let fullPath = dirPath + "/" + dirName;
        let stat = fs.statSync(fullPath);
        let resource: EpubResource;
        let fd = fs.openSync(fullPath, 0o2);
        let buf = new ArrayBuffer(stat.size);
        fs.readSync(fd.fd, buf);
        resource = ResourceUtil.createResource(dirName, new Uint8Array(buf));
        if (resource.getMediaType() == MediaTypeService.XHTML)
            resource.setInputEncoding(defaultHtmlEncoding);
        return resource;
    }
}